package cn.tannn.tconfig.client.repository;

import cn.tannn.tconfig.client.config.ConfigMeta;
import cn.tannn.tconfig.client.http.HttpInvoker;
import com.alibaba.fastjson2.TypeReference;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 获取配置中心中的属性配置
 *
 * @author <a href="https://tannn.cn/">tnnn</a>
 * @version V1.0
 * @date 2024/5/4 下午7:11
 */
@Slf4j
public class TRepositoryImpl implements TRepository {

    final ConfigMeta meta;

    final ScheduledExecutorService executor =  Executors.newScheduledThreadPool(1);

    /**
     * 上一次的数据版本 - 用于对比变化
     */
    Map<String, Long> VERSION_MAP = new HashMap<>();

    /**
     * 当前最新的数据  - 加个小缓存,提高查询性能
     */
    Map<String, Map<String, String>> CONFIG_MAP = new HashMap<>();

    List<TRepositoryChangeListener> listeners =  new ArrayList<>();


    public TRepositoryImpl(ConfigMeta meta) {
        this.meta = meta;
        // 属性值变化监听 - 上一个结束下一个才执行
        executor.scheduleWithFixedDelay(this::heartbeat,
                1000,
                5000,
                TimeUnit.MILLISECONDS);
    }


    @Override
    public void addListener(TRepositoryChangeListener listener) {
        listeners.add(listener);
    }

    @Override
    public Map<String, String> getConfig() {
        // 加个小缓存 - 提高性能
        if (CONFIG_MAP.containsKey(meta.genKey())) {
            return CONFIG_MAP.get(meta.genKey());
        }
        return findAll();
    }





    /**
     * 配置变化探测
     */
    private void heartbeat() {
        String versionPath = meta.versionPath();
        Long version = HttpInvoker.httpGet(versionPath, new TypeReference<>() {
        });
        String key = meta.genKey();
        Long oldVersion = VERSION_MAP.getOrDefault(key, -1L);
        // 新的版本要高与本地缓存的才更新（表示配置中心更新了数据
        if (version > oldVersion) {
            log.debug("[TCONFIG] current=" + version + ", old=" + oldVersion);
            log.debug("[TCONFIG] need update new configs.");
            // 存储新的version
            VERSION_MAP.put(key, version);
            // 存储最新的数据
            HashMap<String, String> newConfigs = findAll();
            CONFIG_MAP.put(key, newConfigs);
            // 变化发送事件 - 让spring env重刷和改变 TConfigServiceImpl.config 的值
            listeners.forEach(listener -> listener.onChange(new TRepositoryChangeListener.ChangeEvent(meta, newConfigs)));
        }

    }



    /**
     * 查询配置中心的属性
     * @return 属性
     */
    private  HashMap<String, String> findAll() {
        log.debug("[TCONFIG] list all configs from t config server.");
        List<Configs> configs = HttpInvoker.httpGet(meta.listPath(), new TypeReference<>() {});
        HashMap<String, String> resultMap = new HashMap<>();
        configs.forEach(c -> resultMap.put(c.getPkey(), c.getPval()));
        return resultMap;
    }
}
